package io.gitee.lglbc.easy.security.core.security;

import io.gitee.lglbc.easy.security.core.exception.TokenException;
import io.gitee.lglbc.easy.security.core.token.EasyPayload;
import io.gitee.lglbc.easy.security.core.token.TokenService;
import io.gitee.lglbc.easy.security.open.EasyLogin;
import io.gitee.lglbc.easy.security.open.EasySecurityResultHandler;
import io.gitee.lglbc.easy.security.open.SimpleUser;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 乐哥聊编程
 */
public class EasyAuthenticationFilter implements Filter {
    @Autowired
    private TokenService tokenService;
    @Autowired
    private EasyLogin easyLogin;
    @Autowired
    private EasySecurityResultHandler easySecurityResultHandler;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (SecurityContextHolder.getContext().getAuthentication() != null) {
            filterChain.doFilter(request, response);
            return;
        }
        Authentication authentication = null;
        try {
            authentication = getAuthentication((HttpServletRequest) request, (HttpServletResponse) response);
            if (authentication == null) {
                filterChain.doFilter(request, response);
                return;
            }
        } catch (TokenException tokenException) {
            easySecurityResultHandler.tokenVerifyFailed((HttpServletResponse) response, tokenException);
            return;
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(request, response);
    }

    private Authentication getAuthentication(HttpServletRequest request, HttpServletResponse response) {
        String header = request.getHeader("Authorization");
        if (header == null || !header.startsWith("Bearer ")) {
            return null;
        }
        return parseToken(header, request, response);
    }

    private UsernamePasswordAuthenticationToken parseToken(String header, HttpServletRequest request, HttpServletResponse response) {
            String token = header.split(" ")[1];
            EasyPayload payloadDto = tokenService.checkToken(token);
            if (payloadDto == null) {
                return null;
            }
            SimpleUser simpleUser = easyLogin.loadUser(payloadDto.getUsername());
            List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
            for (String permission : payloadDto.getAuthorities()) {
                authorityList.add(new SimpleGrantedAuthority(permission));
            }
            return new UsernamePasswordAuthenticationToken(simpleUser, null, authorityList);
    }
}
